package com.gongzhiyun.springboot3test.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gongzhiyun.springboot3test.base.PageBean;
import com.gongzhiyun.springboot3test.base.R;
import com.gongzhiyun.springboot3test.entity.TbActions;
import com.gongzhiyun.springboot3test.entity.TbRoleActions;
import com.gongzhiyun.springboot3test.entity.user.*;
import com.gongzhiyun.springboot3test.interceptor.AppInterceptor;
import com.gongzhiyun.springboot3test.mapper.TbActionsMapper;
import com.gongzhiyun.springboot3test.mapper.TbRoleActionsMapper;
import com.gongzhiyun.springboot3test.mapper.user.*;
import com.gongzhiyun.springboot3test.service.RedisService;
import com.gongzhiyun.springboot3test.service.TbFilesService;
import com.gongzhiyun.springboot3test.service.UserService;
import com.gongzhiyun.springboot3test.utils.EncryptorUtils;
import com.gongzhiyun.springboot3test.utils.Tools;
import com.gongzhiyun.springboot3test.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
    private final TbUserMapper tbUserMapper;
    private final TbUserInfoMapper tbUserInfoMapper;
    private final TbRoleMapper tbRoleMapper;
    private final TbUserExinfoMapper tbUserExinfoMapper;
    private final RedisService redisService;
    private final TbActionsMapper tbActionsMapper;
    private final TbRoleActionsMapper tbRoleActionsMapper;
    private final TbUserFollowsMapper tbUserFollowsMapper;
    private final TbUserPrivateMapper tbUserPrivateMapper;
    private final TbFilesService tbFilesService;

    /**
     * 修改用户头像
     * @return
     */
    @Override
    public R<String> updateLogo(String logo){
        AuthInfo authInfo=AppInterceptor.get();
        int i=tbUserExinfoMapper.updateLogo(logo,authInfo.getUid());
        return i==1?R.ok("修改用户头像成功"):R.fail("修改用户头像失败");
    }

    @Override
    public String logoByUid(Integer uid){
        TbUserExinfo tbUserExinfo=tbUserExinfoMapper.selectById(uid);
        return tbUserExinfo.getLogo();
    }

    /**
     * 用户名查询用户信息
     *
     * @param username
     * @return
     */
    @Override
    public TbUser queryByName(String username) {
        QueryWrapper<TbUser> qw = new QueryWrapper<>();
        qw.eq("username", username);
        return tbUserMapper.selectOne(qw);
    }

    /**
     *通过id查询用户信息
     * @param uid
     * @return
     */
    @Override
    public R<UserInfo> queryById(Integer uid) {
        if (uid == null) {
            return R.fail("未找到该用户");
        }
        //检验登录的用户是否关注
        UserInfo userInfo=queryByIdAll(uid).viewData();
        AuthInfo authInfo=AppInterceptor.get();
        Integer id=authInfo.getUid();
        log.debug("id:{}",id);
        log.debug("uid:{}",uid);
        log.debug("uid.equals(id)================>{}",uid.equals(id));
        if (uid.equals(id)){
           return R.fail("你不认识你自己了吗");
        }
        userInfo.setExinfo(IsFollow(id,uid));

        return R.ok(userInfo);
    }


    /**
     * 用户私信功能
     * @param tbUserPrivate
     * @return
     */
    @Override
    public R<String> privates(TbUserPrivate tbUserPrivate){
        if (tbUserPrivate.getReceiveid() == null) {
            return R.fail("请选择要私信的用户id");
        }
        AuthInfo authInfo=AppInterceptor.get();
        Integer sendid=authInfo.getUid();
        if (sendid==null){
            return R.fail("无认证信息");
        }
        tbUserPrivate.setSendid(sendid);
        int i=tbUserPrivateMapper.insert(tbUserPrivate);
        return i==1?R.ok("私信成功"):R.fail("私信失败");
    }

    /**
     * 查询用户私信内容
     * @param userPrivate
     * @param pageBean
     * @return
     */
    @Override
    public R<List<TbUserPrivate>> queryPrivates(TbUserPrivate userPrivate, PageBean pageBean){
        //建立查询条件
        QueryWrapper<TbUserPrivate> qw=new QueryWrapper<>();
        qw.eq("sendid",userPrivate.getSendid());
        qw.eq("receiveid",userPrivate.getReceiveid());
        //查询排序
        switch (pageBean.getOrder()){
            case 1:
                qw.orderByDesc("lastupdate");
            default:
                qw.orderByAsc("lastupdate");
        }
        //执行分页查询
        Page<TbUserPrivate> pages=tbUserPrivateMapper.selectPage(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), qw);
        pageBean.setTotal(pages.getTotal());
        pageBean.setPages(pages.getPages());

        R<List<TbUserPrivate>> r=R.ok(pages.getRecords());
        r.setPageBean(pageBean);
        return r;
    }

    /**
     * 删除用户私信功能
     * @param id
     * @return
     */
    @Override
    public R<String> delPrivates(Integer id){
        if (id== null) {
            return R.fail("请选择要删除的对象");
        }
        //检验该私信存不存在
        TbUserPrivate tbUserPrivate=tbUserPrivateMapper.selectById(id);
        if (tbUserPrivate == null) {
            return R.fail("删除的对象不存在");
        }
        //获取认证信息
        AuthInfo authInfo=AppInterceptor.get();
        Integer sendid=authInfo.getUid();
        if (sendid==null){
            return R.fail("无认证信息");
        }
        //检验是否是自己发送的
        QueryWrapper<TbUserPrivate> qw=new QueryWrapper<>();
        qw.eq("sendid",sendid);
        if (tbUserPrivateMapper.selectCount(qw)<=0){
            return R.fail("只能操作自己发送的内容");
        }
        int i=tbUserPrivateMapper.deleteById(id);

        return i==1?R.ok("删除成功"):R.fail("删除失败");

    }



    /**
     * 通过uid查询用户完整信息
     *
     * @param uid
     * @return
     */
    @Override
    public UserInfo queryByIdAll(Integer uid) {
        UserInfo info = new UserInfo();
        info.setUser(tbUserMapper.selectById(uid));
        info.setUserInfo(tbUserInfoMapper.selectById(uid));
        info.setRole(tbRoleMapper.selectById(info.getUser().getRole()));
        //更新用户注册天数
        TbUserExinfo tbUserExinfo = tbUserExinfoMapper.selectById(uid);
        Date days = info.getUser().getLastupdate();
        Date date = new Date();
        long now = date.getTime() - days.getTime();
        Integer regDays = (int) (now / (1000 * 60 * 60 * 24));
        tbUserExinfo.setRegDays(regDays);
        tbUserExinfoMapper.updateById(tbUserExinfo);
        info.setExinfo(tbUserExinfo);
        return info;
    }

    /**
     * 用户注册
     *
     * @param user
     * @return
     */
    @Override
    public R<String> reg(UserParams user) {

        //检验用户名是否存在
        TbUser check = queryByName(user.getUsername());
        if (check != null) {
            return R.fail("用户名已存在");
        }
        //密码加密
        String salt = Tools.makeCode(5);
        String pwd = EncryptorUtils.saltMd5(user.getPassword(), salt);
        //添加用户基本信息
        TbUser tbUser = new TbUser();
        tbUser.setUsername(user.getUsername());
        tbUser.setPassword(pwd);
        tbUser.setSalt(salt);
        tbUser.setRole(UserService.role);
        int result = tbUserMapper.insert(tbUser);
        if (result != 1) {
            R.fail("添加用户基本信息失败");
        }
        //添加用户附加信息
        TbUserInfo tbUserInfo = new TbUserInfo();
        tbUserInfo.setUid(tbUser.getUid());
        tbUserInfo.setNickname(Tools.makeRandChinese(3, true));
        result = tbUserInfoMapper.insert(tbUserInfo);
        if (result != 1) {
            R.fail("添加用户附加信息失败");
        }
        //添加用户拓展信息
        TbUserExinfo tbUserExinfo = new TbUserExinfo();
        tbUserExinfo.setUid(tbUser.getUid());
        result = tbUserExinfoMapper.insert(tbUserExinfo);

        return result == 1 ? R.ok("注册成功") : R.fail("注册失败");
    }

    /**
     * 用户登录
     *
     * @param params
     * @return
     */
    @Override
    public R<UserInfo> login(UserParams params) {

        //检验用户是否被禁用
        TbUser check = tbUserMapper.IsDel(params.getUsername());
        if (check != null) {
            return R.fail("用户已被禁用");
        }
        //检验用户名是否正确
        check = queryByName(params.getUsername());
        if (check == null) {
            return R.fail("用户名不正确");
        }
        //检验密码是否正确
        if (!check.getPassword().equals(EncryptorUtils.saltMd5(params.getPassword(), check.getSalt()))) {
            return R.fail("密码不正确");
        }
        //获取并保存token
        String token = UUID.randomUUID().toString();
        redisService.save(token, check.getUid(), 60 * 60 * 24 * 3);
        //返回完整的用户信息
        R<UserInfo> info = R.ok(queryByIdAll(check.getUid()).viewData());
        info.setToken(token);
        return info;
    }

    /**
     * 用户安全退出
     *
     * @return
     */
    @Override
    public R<String> logout() {
        AuthInfo authInfo = AppInterceptor.get();
        if (redisService.has(authInfo.getToken())) {
            redisService.delete(authInfo.getToken());
            return R.ok("安全退出成功");
        }
        return R.fail("退出失败");
    }

    /**
     * 用户修改密码
     *
     * @param pwd
     * @return
     */
    @Override
    public R<String> updatePwd(ParamsPwd pwd) {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.get();
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return R.fail("出错了");
        }
        //验证旧密码
        TbUser check = tbUserMapper.selectById(uid);
        if (check == null) {
            return R.fail("用户不存在");
        }
        if (!check.getPassword().equals(EncryptorUtils.saltMd5(pwd.getOldPwd(), check.getSalt()))) {
            return R.fail("原密码不正确");
        }
        //校验2次新密码是否一样
        if (!pwd.getNewPwd01().equals(pwd.getNewPwd02())) {
            return R.fail("两次密码输入不一致");
        }
        //密码加密
        String password = EncryptorUtils.saltMd5(pwd.getNewPwd02(), check.getSalt());
        //修改用户信息
        check.setPassword(password);
        int result = tbUserMapper.updateById(check);
        if (result != 1) {
            return R.fail("修改失败");
        }
        return R.ok("修改成功");
    }

    /**
     * 修改用户附加信息
     *
     * @param info
     * @return
     */
    @Override
    public R<String> updateInfo(ParamsInfo info) {
        AuthInfo authInfo = AppInterceptor.get();
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return R.fail("出错了");
        }
        TbUserInfo userInfo = tbUserInfoMapper.selectById(uid);
        if (userInfo == null) {
            return R.fail("出错了");
        }
        userInfo.setWechat(info.getWechat());
        userInfo.setInfo(info.getInfo());
        userInfo.setQq(info.getQq());
        userInfo.setSex(info.getSex());
        userInfo.setNickname(info.getNickname());
        int result = tbUserInfoMapper.updateById(userInfo);
        return result == 1 ? R.ok("修改成功") : R.fail("修改失败");
    }

    /**
     * 获取登录的用户信息
     *
     * @return
     */
    @Override
    public R<UserInfo> getLoginInfo() {
        AuthInfo authInfo = AppInterceptor.get();
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return R.fail("无认证信息");
        }
        UserInfo userInfo = queryByIdAll(uid).viewData();
        return userInfo == null ? R.fail("") : R.ok(userInfo);
    }

    /**
     * 管理员删除，恢复用户操作
     *
     * @return
     */
    @Override
    public R<String> isDelUser(ParamsDel paramsDel) {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.get();
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return R.fail("出错了");
        }
        //校验登录的用户是否是管理员
        TbUser user = tbUserMapper.selectById(uid);
        if (user.getRole() != 1) {
            return R.fail("无权限");
        }
        //校验用户是否已经被禁用
        TbUser check = tbUserMapper.IsDel(paramsDel.getId());
        if (check == null) {
            //用户未被禁用，点击则禁用用户
            int i = tbUserMapper.deleteById(paramsDel.getId());
            return i == 1 ? R.ok("操作成功") : R.fail("操作失败");
        }
        //用户被删除,点击则恢复用户
        int i = tbUserMapper.restoreUser(paramsDel.getId());
        //需说明删除理由
        if (paramsDel.getReason() == null) {
            return R.fail("请说明删除理由");
        }
        return i == 1 ? R.ok("操作成功") : R.fail("操作失败");
    }

    /**
     * 用户关注用户
     *
     * @param id
     * @return
     */
    @Override
    public R<String> concern(Integer id) {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.get();
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return R.fail("出错了");
        }
        TbUser user = tbUserMapper.selectById(id);
        if (user == null) {
            return R.fail("关注的用户不存在");
        }
        //检验是否已经关注
        QueryWrapper<TbUserFollows> qw = new QueryWrapper<>();
        qw.eq("follow", uid);
        qw.eq("followed", id);
        TbUserFollows follows = tbUserFollowsMapper.selectOne(qw);
        if (follows != null) {
            //用户已经关注,点击则为取消关注
            //删除关注信息
            int i = tbUserFollowsMapper.deleteById(follows.getId());
            if (i != 1) {
                return R.fail("操作失败");
            }
            //取消关注，我关注的人数-1，被取消的用户粉丝数-1
            i = tbUserExinfoMapper.DecfollowMines(id);
            if (i != 1) {
                return R.fail("操作失败");
            }
            i = tbUserExinfoMapper.DecmineFollows(uid);
            return i == 1 ? R.ok("操作成功") : R.fail("操作失败");
        }
        //未关注则增加关注信息
        follows = new TbUserFollows();
        follows.setFollow(uid);
        follows.setFollowed(id);
        int i = tbUserFollowsMapper.insert(follows);
        if (i != 1) {
            return R.fail("关注失败");
        }
        //增加关注，我关注的人数+1，被关注的用户粉丝数+1
        i = tbUserExinfoMapper.addmineFollows(uid);
        if (i != 1) {
            return R.fail("操作失败");
        }
        i = tbUserExinfoMapper.addfollowMines(id);
        if (i != 1) {
            return R.fail("操作失败");
        }

        return R.ok("关注成功");
    }

    /**
     * 查询用户的关注列表
     *
     * @param uid
     * @param pageBean
     * @return
     */
    @Override
    public R<List<UserInfo>> queryFollow(Integer uid, PageBean pageBean) {
        //查询出所有的uid用户关注用户的uid
        QueryWrapper<TbUserFollows> qw = new QueryWrapper<>();
        qw.eq("follow", uid);
        //执行分页查询
        Page<TbUserFollows> pages = tbUserFollowsMapper.selectPage(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), qw);
        pageBean.setTotal(pages.getTotal());
        pageBean.setPages(pages.getPages());

        //遍历
        List<UserInfo> info = new ArrayList<>();
        for (TbUserFollows tb : pages.getRecords()) {
            UserInfo userInfo = queryByIdAll(tb.getFollowed()).viewData();
            userInfo.setExinfo(IsFollow(uid, tb.getFollowed()));
            info.add(userInfo);
        }

        R<List<UserInfo>> r = R.ok("查询成功", info);
        r.setPageBean(pageBean);

        return r;
    }

    /**
     * 判断用户之间是否关注，被关注
     *
     * @return
     */
    @Override
    public TbUserExinfo IsFollow(Integer uid, Integer id) {
        TbUserExinfo exinfo = tbUserExinfoMapper.selectById(id);
        QueryWrapper<TbUserFollows> qw = new QueryWrapper<>();
        qw.eq("follow", uid);
        qw.eq("followed", id);
        if (tbUserFollowsMapper.selectCount(qw) > 0) {
            exinfo.setMineFollow(true);
        }
        qw = new QueryWrapper<>();
        qw.eq("followed", uid);
        qw.eq("follow", id);
        if (tbUserFollowsMapper.selectCount(qw) > 0) {
            exinfo.setFollowMine(true);
        }
        return exinfo;
    }


    /**
     * 查询用户的粉丝列表
     *
     * @param uid
     * @param pageBean
     * @return
     */
    @Override
    public R<List<UserInfo>> queryFollowed(Integer uid, PageBean pageBean) {
        //查询所有用户的粉丝id
        QueryWrapper<TbUserFollows> qw = new QueryWrapper<>();
        qw.eq("followed", uid);
        //执行分页查询
        Page<TbUserFollows> pages = tbUserFollowsMapper.selectPage(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), qw);
        pageBean.setTotal(pages.getTotal());
        pageBean.setPages(pages.getPages());
        //遍历
        List<UserInfo> info = new ArrayList<>();
        for (TbUserFollows tb : pages.getRecords()) {
            UserInfo userInfo = queryByIdAll(tb.getFollow()).viewData();
            userInfo.setExinfo(IsFollow(uid, tb.getFollow()));
            info.add(userInfo);
        }
        R<List<UserInfo>> listR = R.ok(info);
        listR.setPageBean(pageBean);
        return listR;
    }

    /**
     * api权限管理
     *
     * @return
     */
    @Override
    public boolean checkAuth() {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.get();
        //校验api路径是否在数据库管理
        QueryWrapper<TbActions> tbActionsQueryWrapper = new QueryWrapper<>();
        tbActionsQueryWrapper.eq("mapping", authInfo.getMapping());
        tbActionsQueryWrapper.eq("method", authInfo.getMethod());
        TbActions tbAction = tbActionsMapper.selectOne(tbActionsQueryWrapper);
        log.debug("tbActions===>{}", tbAction);
        if (tbAction == null) {
            //不在数据库内直接通过
            return true;
        }
        //获取登录用户信息
        Integer uid = authInfo.getUid();
        if (uid == null) {
            return false;
        }
        TbUser user = tbUserMapper.selectById(uid);
        if (user == null) {
            return false;
        }
        //校验登录的角色是否拥有访问次api的权限
        QueryWrapper<TbRoleActions> tbRoleActionsQueryWrapper = new QueryWrapper<>();
        tbRoleActionsQueryWrapper.eq("role", user.getRole());
        tbRoleActionsQueryWrapper.eq("action", tbAction.getId());
        TbRoleActions tbRoleActions = tbRoleActionsMapper.selectOne(tbRoleActionsQueryWrapper);
        return tbRoleActions != null;
    }


}
